﻿using System;
using System.Linq;
using UnityEngine;
using Object = UnityEngine.Object;

public class CameraManager {
	// === Public =====================================================================================================
	public static CameraManager CreateInstance() {
		var instance = new CameraManager();
		return instance;
	}

	public void Create() {
		CreateGo();
		if (SettingsGameModel.IsCamera2D) {
			InitializeCamera2D();
		} else {
			InitializeCamera3D();
		}
	}

	public void Destroy() {
		if (_go == null) {
			return;
		}
		Object.Destroy(_go);
		_go = null;
	}

	public void UpdateCameraSize() {
		if (SettingsGameModel.IsCamera2D) {
			InitializeCamera2D();
		}
	}

	// === Private ====================================================================================================
	private GameObject _go;

	private void CreateGo() {
		_go = Tools.Prefab.Create<GameObject>(Constants.Resources.Prefabs.Camera.GAME_CAMERA);
	}

	private void InitializeCamera2D() {
		var screenSize = new Vector2(Screen.width, Screen.height);
		var fieldSize = SettingsLevelModel.FieldSize;
		const int height = 20;
		const float сellHalf = Constants.CELL_LENGTH_HALF;
		var pos = new Vector3(fieldSize.x * .5f - сellHalf, height, fieldSize.y * .5f - сellHalf);
		_go.transform.position = pos;
		_go.transform.rotation = Quaternion.Euler(new Vector3(90, 0, 0));
		_go.camera.orthographic = true;

		const int borders = 2;
		var cellX = screenSize.x / (fieldSize.x + borders);
		var cellY = screenSize.y / (fieldSize.y + borders);
		if (cellX < cellY) {
			var screenRest = screenSize.y - screenSize.x;
			var offset = screenRest * .5f / cellX;
			_go.camera.orthographicSize = offset + (fieldSize.x + borders) * .5f;
		} else {
			_go.camera.orthographicSize = (fieldSize.y + borders) * .5f;
		}
	}

	private void InitializeCamera3D() {
		_go.camera.orthographic = false;

		var view = GetCameraView(_go);
		view.SetTarget(GameData.GetInstance.Bodies.First().GameObject.transform);
	}

	private CameraView GetCameraView(GameObject go) {
		var cameraView = go.GetComponent<CameraView>();
		if (cameraView == null) {
			throw new ArgumentNullException("CameraView is null");
		}
		return cameraView;
	}
}
